﻿/*
 * 版权所有 (c) 2019 Made With Monster Love (Pty) Ltd
 * 
 * 任何获得本软件及相关文档文件副本的人（“软件”），
 * 可以在不受限制的情况下使用、复制、修改、合并、发布、
 * 分发、子许可和/或出售软件的副本，并允许软件接收者
 * 进行上述操作，前提是遵守以下条件：
 * 
 * 上面的版权声明和许可声明应包含在本软件的所有副本或主要部分中。
 * 
 * 软件按“原样”提供，不附带任何形式的明示或暗示担保，
 * 包括但不限于对适销性、特定用途适用性和非侵权的担保。
 * 在任何情况下，作者或版权持有人均不对任何索赔、
 * 损害或其他责任承担责任，无论是在合同诉讼、侵权行为或其他
 * 侵权行为中，还是源于软件或软件的使用或其他交易。
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using Cysharp.Threading.Tasks;
using MyFrame.Mono;
using Unity.VisualScripting;
using UnityEngine;
using Object = System.Object;

namespace MonsterLove.StateMachine
{
	/// <summary>
	/// 处理不同的状态转换方式  safe是 over是停止协程
	/// </summary>
	public enum StateTransition
	{

		Safe,
		Overwrite,
	}

	public interface IStateMachine<TDriver>
	{
		MonoBehaviour Component { get; }
		TDriver Driver { get; }
		bool IsInTransition { get; }
	}

	public class StateMachine<TState> : StateMachine<TState, StateDriverRunner> where TState : struct, IConvertible, IComparable
	{
		public StateMachine(MonoBehaviour component) : base(component)
		{
		}

		public StateMachine(MonoBehaviour component, bool isAutoAnimating) : base(component, isAutoAnimating) { }
	}

	public class StateMachine<TState, TDriver> : IStateMachine<TDriver> where TState : struct, IConvertible, IComparable where TDriver : class, new()
	{
		public event Action<TState> Changed;

		public bool reenter = false;
		private MonoBehaviour component;

		private StateMapping<TState, TDriver> lastState;
		private StateMapping<TState, TDriver> currentState;


		private StateMapping<TState, TDriver> destinationState;
		private StateMapping<TState, TDriver> queuedState;
		private TDriver rootDriver;

		private Dictionary<object, StateMapping<TState, TDriver>> stateLookup;
		private Func<TState, int> enumConverter;

		private bool isInTransition = false;
		private IEnumerator currentTransition;
		private IEnumerator exitRoutine;
		private IEnumerator enterRoutine;
		private IEnumerator queuedChange;

		private static BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;


		private bool isAutoAnimating = false;
		private Dictionary<string, AnimatorControllerParameterType> paramExists = new();
		private Animator[] animators;


		#region Initialization
		/// <summary>
		/// 自定义的构造函数，用于开启自动动画
		/// </summary>
		/// <param name="component"></param>
		/// <param name="isAutoAnimating"></param>
		public StateMachine(MonoBehaviour component, bool isAutoAnimating)
		{
			this.isAutoAnimating = isAutoAnimating;

			// 提前保存   这里默认多个动画机的命名是相同的
			animators = component.GetComponentsInChildren<Animator>();
			foreach (var animator in animators)
			{
				foreach (AnimatorControllerParameter param in animator.parameters)
				{
					paramExists[param.name] = param.type;
				}
			}

			Init(component);
		}

		public StateMachine(MonoBehaviour component)
		{
			Init(component);
		}

		private void Init(MonoBehaviour component)
		{
			this.component = component;

			//编译器技巧，从泛型枚举中获取整数
			Func<int, int> identity = Identity;
			enumConverter = Delegate.CreateDelegate(typeof(Func<TState, int>), identity.Method) as Func<TState, int>;

			//定义状态  获取枚举值  
			var enumValues = Enum.GetValues(typeof(TState));
			if (enumValues.Length < 1)
			{
				throw new ArgumentException("提供给Initialize的枚举必须至少有一个可见定义");
			}

			var enumBackingType = Enum.GetUnderlyingType(typeof(TState));
			if (enumBackingType != typeof(int))
			{
				throw new ArgumentException("仅支持基础类型为int的枚举");
			}

			//在驱动类中查找所有项目   似乎是找自定义的StateEvent方法
			// public class Driver
			// {
			//     StateEvent Foo;        <- 选择
			//     StateEvent<int> Boo;   <- 选择
			//     float x;               <- 抛出异常
			// }
			List<FieldInfo> eventFields = GetFilteredFields(typeof(TDriver), "MonsterLove.StateMachine.StateEvent");
			Dictionary<string, FieldInfo> eventFieldsLookup = CreateFieldsLookup(eventFields);

			//实例化驱动程序
			// driver = new Driver();
			// 对于每个StateEvent：
			//   StateEvent foo = new StateEvent(isAllowed, getStateInt, capacity);
			rootDriver = CreateDriver(IsDispatchAllowed, GetStateInt, enumValues.Length, eventFields);

			// 为枚举中定义的每个状态创建状态映射
			stateLookup = CreateStateLookup(this, enumValues);

			//收集目标组件的方法
			MethodInfo[] methods = component.GetType().GetMethods(bindingFlags);

			//将方法绑定到状态
			for (int i = 0; i < methods.Length; i++)
			{
				TState state;
				string evtName;
				if (!ParseName(methods[i], out state, out evtName))
				{
					continue; //跳过无法解析State_Event命名约定的方法
				}

				StateMapping<TState, TDriver> mapping = stateLookup[state];

				if (eventFieldsLookup.ContainsKey(evtName))
				{
					//将方法绑定到TDriver中定义的方法
					// driver.Foo.AddListener(StateOne_Foo);
					FieldInfo eventField = eventFieldsLookup[evtName];
					BindEvents(rootDriver, component, state, enumConverter(state), methods[i], eventField);
				}
				else
				{
					//绑定Enter、Exit和Finally方法
					BindEventsInternal(mapping, component, methods[i], evtName);
				}
			}

			//创建nil状态映射
			currentState = null;
		}

		#region 自动动画
		// todo 应该单独封装一个实体FSM
		public event Action OnTriggerAnimationEnd;
		private string preAttackState;
		/// <summary>
		/// 变更状态调用两次，关闭旧的，开启新的
		/// </summary>
		/// <param name="isEnter"></param>
		private void SetAnimationParam(bool isEnter, bool isBreakAnimation = false)
		{
			if (currentState.state.ToString().Contains("Blackhole"))
			{
				Debug.Log("test");
			}
			Debug.Log("状态切换：" + currentState.state.ToString() + " " + isEnter);

			foreach (var animator in animators)
			{
				if (paramExists.ContainsKey(lastState?.state.ToString() ?? "") &&
				paramExists[lastState.state.ToString()] == AnimatorControllerParameterType.Trigger)
				{
					animator.ResetTrigger(lastState.state.ToString());
				}

				if (paramExists.ContainsKey(currentState.state.ToString()))
				{
					if (paramExists[currentState.state.ToString()] == AnimatorControllerParameterType.Trigger)
					{
						if (isEnter)
						{
							animator.SetTrigger(currentState.state.ToString());
						}
					}
					else if (paramExists[currentState.state.ToString()] == AnimatorControllerParameterType.Bool)
					{
						animator.SetBool(currentState.state.ToString(), isEnter);
					}
				}
				else
				{
					//抽象状态  设置的是上一个动画的参数  没有动画，也不影响动画
					animator.SetBool(lastState?.state.ToString(), isEnter);
				}
			}

			//获取当前动画时长，结束自动设置回上一个非触发器状态
			if (isEnter && paramExists.ContainsKey(currentState.state.ToString()) && paramExists[currentState.state.ToString()] == AnimatorControllerParameterType.Trigger)
			{
				WaitAnimationEndToBeforeState().Forget();
			}
		}
		private async UniTask WaitAnimationEndToBeforeState()
		{
			// // 创建一个任务数组，等待所有动画完成
			// var tasks = new UniTask[animators.Length];

			// for (int i = 0; i < animators.Length; i++)
			// {
			// 	tasks[i] = WaitForAnimator(animators[i]);
			// }

			// // 等待所有动画任务并行完成
			// await UniTask.WhenAll(tasks);
			await WaitForAnimator(animators[0]);

			// 所有动画完成后切换  默认状态
			OnTriggerAnimationEnd?.Invoke();
		}
		// 等待单个Animator的动画播放结束  
		private async UniTask WaitForAnimator(Animator animator)
		{
			// 参数的设置后 动画理论上下一帧修改，但是实际上要等好几帧
			// 上一个动画没有退出时间，直接等一个循环就是真实动画

			// 等待当前动画开始
			await AnimationTool.AwaitAnimStartByName(animator, null, GetCurrentRealAnimStateName(animator));

			AnimatorStateInfo currentAm = animator.GetCurrentAnimatorStateInfo(0);
			currentAm = animator.GetCurrentAnimatorStateInfo(0);
			// 得到真实动画长度
			var duration = currentAm.length;

			float preProcessTime = currentState.state.ToString().Contains("DoubleAttack") ? duration * 0.2f : 0; // 计算提前处理时间（动画总时长的 25%）

			//获取上次攻击   约定combo参数就是 攻击状态名+ Combo
			if (currentState.state.ToString().Contains("DoubleAttack"))
				preAttackState = GetAttackStateName(animator);
			// 等待动画完成
			float waitTime = duration - preProcessTime;
			if (waitTime > 0)
				// 等待当前动画结束
				await AnimationTool.AwaitAnimEndByName(animator, null, GetCurrentRealAnimStateName(animator));
			// await UniTask.Delay((int)(waitTime * 1000), DelayType.Realtime, PlayerLoopTiming.Update);
		}
		private string GetAttackStateName(Animator animator)
		{
			return currentState.state.ToString() + (animator.GetInteger(currentState.state.ToString() + "Combo") + 1);
		}
		private string GetCurrentRealAnimStateName(Animator animator)
		{
			// 根据约定来
			AnimatorStateInfo currentAm = animator.GetCurrentAnimatorStateInfo(0);
			if (currentState.state.ToString().Contains("DoubleAttack"))
			{
				return currentState.state.ToString() + (animator.GetInteger(currentState.state.ToString() + "Combo") + 1);
			}
			return currentState.state.ToString();
		}
		#endregion

		static List<FieldInfo> GetFilteredFields(Type type, string searchTerm)
		{
			List<FieldInfo> list = new List<FieldInfo>();

			FieldInfo[] fields = type.GetFields(bindingFlags);

			for (int i = 0; i < fields.Length; i++)
			{
				FieldInfo item = fields[i];
				if (item.FieldType.ToString().Contains(searchTerm))
				{
					list.Add(item);
				}
				else
				{
					throw new ArgumentException(string.Format("{0}包含不受支持的类型{1}", type, item.FieldType));
				}
			}

			return list;
		}

		static Dictionary<string, FieldInfo> CreateFieldsLookup(List<FieldInfo> fields)
		{
			var dict = new Dictionary<string, FieldInfo>();

			for (int i = 0; i < fields.Count; i++)
			{
				FieldInfo item = fields[i];

				dict.Add(item.Name, item);
			}

			return dict;
		}

		static Dictionary<object, StateMapping<TState, TDriver>> CreateStateLookup(StateMachine<TState, TDriver> fsm, Array values)
		{
			var stateLookup = new Dictionary<object, StateMapping<TState, TDriver>>();
			for (int i = 0; i < values.Length; i++)
			{
				var mapping = new StateMapping<TState, TDriver>(fsm, (TState)values.GetValue(i), fsm.GetState);
				stateLookup.Add(mapping.state, mapping);
			}

			return stateLookup;
		}

		static TDriver CreateDriver(Func<bool> isInvokeAllowedCallback, Func<int> getStateIntCallback, int capacity, List<FieldInfo> fieldInfos)
		{
			if (fieldInfos == null)
			{
				throw new ArgumentException(string.Format("参数不能为null。回调{0}字段信息{1}", isInvokeAllowedCallback, fieldInfos));
			}

			TDriver driver = new TDriver();

			for (int i = 0; i < fieldInfos.Count; i++)
			{
				//driver.Event = new StateEvent(callback)
				FieldInfo fieldInfo = fieldInfos[i]; //事件
				ConstructorInfo constructorInfo = fieldInfo.FieldType.GetConstructor(new Type[] { typeof(Func<bool>), typeof(Func<int>), typeof(int) }); //StateEvent(Func<Bool> invokeAllowed, Func<in> getState, int capacity)
				object obj = constructorInfo.Invoke(new object[] { isInvokeAllowedCallback, getStateIntCallback, capacity }); //obj = new StateEvent(Func<bool> isInvokeAllowed, Func<int> stateProvider, int capacity);
				fieldInfo.SetValue(driver, obj); //driver.Event = obj;
			}

			return driver;
		}

		static bool ParseName(MethodInfo methodInfo, out TState state, out string eventName)
		{
			state = default(TState);
			eventName = null;

			if (methodInfo.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Length != 0)
			{
				return false;
			}

			string name = methodInfo.Name;
			int index = name.IndexOf('_');

			//忽略没有下划线的函数
			if (index < 0)
			{
				return false;
			}

			string stateName = name.Substring(0, index);
			eventName = name.Substring(index + 1);

			try
			{
				state = (TState)Enum.Parse(typeof(TState), stateName);
			}
			catch (ArgumentException)
			{
				//不是状态枚举中列出的方法
				return false;
			}

			return true;
		}

		static void BindEvents(TDriver driver, Component component, TState state, int stateInt, MethodInfo stateTargetDef, FieldInfo driverEvtDef)
		{
			var genericTypes = driverEvtDef.FieldType.GetGenericArguments(); //从StateEvent<T1,T2,...TN>获取T1,T2,...TN
			var actionType = GetActionType(genericTypes); //typeof(Action<T1,T2,...TN>)

			//evt.AddListener(State_Method); 
			var obj = driverEvtDef.GetValue(driver); //driver.Foo
			var addMethodInfo = driverEvtDef.FieldType.GetMethod("AddListener", bindingFlags); // driver.Foo.AddListener

			Delegate del = null;
			try
			{
				del = Delegate.CreateDelegate(actionType, component, stateTargetDef);
			}
			catch (ArgumentException)
			{
				throw new ArgumentException(string.Format("状态 ({0}_{1}) 需要回调类型: {2}, 找到类型: {3}", state, driverEvtDef.Name, actionType, stateTargetDef));
			}

			addMethodInfo.Invoke(obj, new object[] { stateInt, del }); //driver.Foo.AddListener(stateInt, component.State_Event);
		}

		static void BindEventsInternal(StateMapping<TState, TDriver> targetState, Component component, MethodInfo method, string evtName)
		{
			switch (evtName)
			{
				case "Enter":
					if (method.ReturnType == typeof(IEnumerator))
					{
						targetState.hasEnterRoutine = true;
						targetState.EnterRoutine = CreateDelegate<Func<IEnumerator>>(method, component);
					}
					else
					{
						targetState.hasEnterRoutine = false;
						targetState.EnterCall = CreateDelegate<Action>(method, component);
					}
					break;
				case "Exit":
					if (method.ReturnType == typeof(IEnumerator))
					{
						targetState.hasExitRoutine = true;
						targetState.ExitRoutine = CreateDelegate<Func<IEnumerator>>(method, component);
					}
					else
					{
						targetState.hasExitRoutine = false;
						targetState.ExitCall = CreateDelegate<Action>(method, component);
					}

					break;
				case "Finally":
					targetState.Finally = CreateDelegate<Action>(method, component);
					break;
			}
		}

		static V CreateDelegate<V>(MethodInfo method, Object target) where V : class
		{
			var ret = (Delegate.CreateDelegate(typeof(V), target, method) as V);

			if (ret == null)
			{
				throw new ArgumentException("无法为方法创建委托 " + method.Name);
			}

			return ret;
		}

		static Type GetActionType(Type[] genericArgs)
		{
			switch (genericArgs.Length)
			{
				case 0:
					return typeof(Action);
				case 1:
					return typeof(Action<>).MakeGenericType(genericArgs);
				case 2:
					return typeof(Action<,>).MakeGenericType(genericArgs);
				default:
					throw new ArgumentOutOfRangeException(string.Format("无法使用{0}个类型参数创建Action类型", genericArgs.Length));
			}
		}

		#endregion

		#region ChangeStates

		public void ChangeState(TState newState, bool isBreakAnimation = false)
		{
			// Debug.Log("ChangeState" + newState.ToString());
			ChangeState(newState, StateTransition.Safe, isBreakAnimation);
		}

		public void ChangeState(TState newState, StateTransition transition, bool isBreakAnimation = false)
		{
			if (stateLookup == null)
			{
				throw new Exception("状态尚未配置，请在尝试设置状态之前调用初始化");
			}

			if (!stateLookup.ContainsKey(newState))
			{
				throw new Exception("找不到名称为 " + newState.ToString() + " 的状态。请确保您使用的是初始化状态机的正确类型");
			}

			var nextState = stateLookup[newState];

			if (!reenter && currentState == nextState)
			{
				return;
			}

			//取消任何排队的更改。
			if (queuedChange != null)
			{
				component.StopCoroutine(queuedChange);
				queuedChange = null;
			}

			switch (transition)
			{
				//case StateMachineTransition.Blend:
				//不做任何事情 - 允许状态转换重叠。这是一个愚蠢的想法，因为前一个状态可能会触发新的更改。
				//更好的方法是同时启动两个协程。即不要在开始之前等待退出。
				//在覆盖方面如何工作？
				//有没有办法使这变得安全，我不认为有。
				//break;
				case StateTransition.Safe:
					if (isInTransition)
					{
						if (exitRoutine != null) //我们已经在退出当前状态，前往前一个目标状态
						{
							//用我们的新目标覆盖
							destinationState = nextState;
							return;
						}

						if (enterRoutine != null) //我们已经在进入前一个目标状态。需要等待完成并调用退出例程。
						{
							//该死，我需要测试这个
							queuedChange = WaitForPreviousTransition(nextState);
							component.StartCoroutine(queuedChange);
							return;
						}
					}

					break;
				case StateTransition.Overwrite:
					if (currentTransition != null)
					{
						component.StopCoroutine(currentTransition);
					}

					if (exitRoutine != null)
					{
						component.StopCoroutine(exitRoutine);
					}

					if (enterRoutine != null)
					{
						component.StopCoroutine(enterRoutine);
					}

					//注意：如果我们当前处于EnterRoutine中，并且Exit也是例程，这将在ChangeToNewStateRoutine()中被跳过
					break;
			}


			if ((currentState != null && currentState.hasExitRoutine) || nextState.hasEnterRoutine)
			{
				isInTransition = true;
				currentTransition = ChangeToNewStateRoutine(nextState, transition, isBreakAnimation);
				component.StartCoroutine(currentTransition);
			}
			else //同一帧转换，没有协程存在
			{
				destinationState = nextState; //在这里分配，以便Exit()有一个有效的引用

				if (currentState != null)
				{
					//额外操作，自动动画
					if (isAutoAnimating)
						SetAnimationParam(false);

					currentState.ExitCall();
					currentState.Finally();
				}

				lastState = currentState;
				currentState = destinationState;
				if (currentState != null)
				{
					//额外操作，自动动画
					if (isAutoAnimating)
						SetAnimationParam(true, isBreakAnimation);

					currentState.EnterCall();

					if (Changed != null)
					{
						Changed((TState)currentState.state);
					}
				}

				isInTransition = false;
			}
		}

		private IEnumerator ChangeToNewStateRoutine(StateMapping<TState, TDriver> newState, StateTransition transition, bool isBreakAnimation = false)
		{
			destinationState = newState; //缓存此值，以便我们可以覆盖它并劫持转换

			if (currentState != null)
			{
				//额外操作，自动动画
				if (isAutoAnimating)
					SetAnimationParam(false);

				if (currentState.hasExitRoutine)
				{
					exitRoutine = currentState.ExitRoutine();

					if (exitRoutine != null && transition != StateTransition.Overwrite) //如果我们正在覆盖，则不等待退出
					{
						yield return component.StartCoroutine(exitRoutine);
					}

					exitRoutine = null;
				}
				else
				{
					currentState.ExitCall();
				}

				currentState.Finally();
			}

			lastState = currentState;
			currentState = destinationState;

			if (currentState != null)
			{
				//额外操作，自动动画
				if (isAutoAnimating)
					SetAnimationParam(true, isBreakAnimation);

				if (currentState.hasEnterRoutine)
				{
					enterRoutine = currentState.EnterRoutine();

					if (enterRoutine != null)
					{
						yield return component.StartCoroutine(enterRoutine);
					}

					enterRoutine = null;
				}
				else
				{
					currentState.EnterCall();
				}

				//仅在进入转换开始后广播更改。 
				if (Changed != null)
				{
					Changed((TState)currentState.state);
				}
			}

			isInTransition = false;
		}

		IEnumerator WaitForPreviousTransition(StateMapping<TState, TDriver> nextState)
		{
			queuedState = nextState; //缓存此值，以便fsm.NextState准确

			while (isInTransition)
			{
				yield return null;
			}

			queuedState = null;
			ChangeState((TState)nextState.state);
		}

		#endregion

		#region Properties & Helpers

		public bool LastStateExists
		{
			get { return lastState != null; }
		}

		public TState LastState
		{
			get
			{
				if (lastState == null)
				{
					throw new NullReferenceException("在至少调用两次ChangeState()之前不能访问LastState");
				}

				return (TState)lastState.state;
			}
		}

		public TState NextState
		{
			get
			{
				if (queuedState != null) //在安全模式下，有时我们需要等待目标状态完成，并将其存储在queued state中
				{
					return (TState)queuedState.state;
				}

				if (destinationState == null)
				{
					return State;
				}

				return (TState)destinationState.state;
			}
		}

		public TState State
		{
			get
			{
				if (currentState == null)
				{
					throw new NullReferenceException("在至少调用一次ChangeState()之前不能访问State");
				}

				return (TState)currentState.state;
			}
		}

		public bool IsInTransition
		{
			get { return isInTransition; }
		}

		public TDriver Driver
		{
			get { return rootDriver; }
		}

		public MonoBehaviour Component
		{
			get { return component; }
		}

		//格式化为方法，以便可以传递为Func<TState>
		private TState GetState()
		{
			return State;
		}

		private int GetStateInt()
		{
			return enumConverter(State);
		}

		//编译器技巧，从泛型枚举中获取整数
		private static int Identity(int x)
		{
			return x;
		}

		private bool IsDispatchAllowed()
		{
			if (currentState == null)
			{
				return false;
			}

			if (IsInTransition)
			{
				return false;
			}

			return true;
		}

		#endregion

		#region Static API

		//静态


		/// <summary>
		/// 检查一个MonoBehaviour，根据提供的枚举定义状态方法，并返回一个用于状态转换的状态机实例。
		/// </summary>
		/// <param name="component">定义了状态方法的组件</param>
		/// <returns>一个有效状态机实例，用于管理MonoBehaviour的状态转换</returns>
		public static StateMachine<TState> Initialize(MonoBehaviour component)
		{
			var engine = component.GetComponent<StateMachineRunner>();
			if (engine == null) engine = component.gameObject.AddComponent<StateMachineRunner>();

			return engine.Initialize<TState>(component);
		}

		/// <summary>
		/// 检查一个MonoBehaviour，根据提供的枚举定义状态方法，并返回一个用于状态转换的状态机实例。 
		/// </summary>
		/// <param name="component">定义了状态方法的组件</param>
		/// <param name="startState">默认的起始状态</param>
		/// <returns>一个有效状态机实例，用于管理MonoBehaviour的状态转换</returns>
		public static StateMachine<TState> Initialize(MonoBehaviour component, TState startState)
		{
			var engine = component.GetComponent<StateMachineRunner>();
			if (engine == null) engine = component.gameObject.AddComponent<StateMachineRunner>();

			return engine.Initialize<TState>(component, startState);
		}


		#endregion



		#region  扩展
		public TState CurrentState => currentState.state;
		public void ClearLastState()
		{
			foreach (var animator in animators)
			{
				animator.SetBool(lastState.state.ToString(), false);
			}
		}
		public void ClearAllAnim()
		{
			foreach (var animator in animators)
			{
				foreach (AnimatorControllerParameter param in animator.parameters)
				{
					if (param.type == AnimatorControllerParameterType.Trigger)
					{
						animator.ResetTrigger(param.name);
					}
					else if (param.type == AnimatorControllerParameterType.Bool)
					{
						animator.SetBool(param.name, false);
					}
					else if (param.type == AnimatorControllerParameterType.Int)
					{
						animator.SetInteger(param.name, 0);
					}
					else if (param.type == AnimatorControllerParameterType.Float)
					{
						animator.SetFloat(param.name, 0f);
					}
				}
			}
		}

		#endregion
	}
}